﻿package core{
	import flash.xml.XMLNode;
	dynamic public class XMLOperate {
		public var xml:XML
		public static const emptyXML:XML=new XML
		public static const emptyXMLList:XMLList = new XMLList
		
		public var xmlname:String
		public var xmltext:String
		public var xmlcdata:String
		public var value:String
		public var id:int
		
		public function XMLOperate(xmldata:XML = null) {
			if (xmldata != null) {
				reset(xmldata)
			}
		}
		public function destroy():void {
			for (var i:int = 0; i < _list.length; i++) {
				if (_list[i] is XMLOperate) {
					XMLOperate(_list[i]).destroy()
				}else {
					_list[i] = null
				}
			}
			_list = [];
			xml = null
		}
		public final function clone():XMLOperate {
			return new XMLOperate(xml)
		}
		public final function reset(xmldata:XML):void {
			xml = xmldata
			_depth = _depthLoop(new XMLList(xml), 0)
			addXML(xml)
		}
		public final function toString():String {
			return xml.toXMLString()
		}
		public final function addXML(xmlnode:XML):void {
			var xmlnodeStr:String = xmlnode.toXMLString()
			if (xmlnodeStr.indexOf("<![") ==0) {
				add("xmlcdata", xmlnodeStr.substring(9, xmlnodeStr.length - 3))
			}else if(xmlnodeStr.indexOf("<")){
				add("xmltext", xmlnodeStr)
			}
			if (xmlnode.name() != null) {
				add("xmlname",formatName(xmlnode.name()))
			}
			if (xmlnode.attributes().length() != 0) {
				var xnlength:uint = xmlnode.attributes().length()
				for (var i:uint = 0 ; i < xnlength; i++) {
					add(xmlnode.attributes()[i].name(),xmlnode.attributes()[i].valueOf())
				}
			}
			if (xmlnode.children().length() != 0) {
				var xnChildLength:uint = xmlnode.children().length()
				_length = xnChildLength
				for (var j:uint = 0 ; j < xnChildLength; j++) {
					var tmp_xml:XML=new XML(xmlnode.child(j).toXMLString())
					var xo:XMLOperate=new XMLOperate(tmp_xml)
					add(j.toString(), xo)
					xo.add("id", j)
					var str:String = tmp_xml.name()
					if (str == null) {
						add("value",xo)
					}else {
						add(str,xo)
					}
				}
			}
		}
		public final function add(name:String, value:*= null):void {
			try {
				name = formatName(name)
				this[name] = value
				_list.push(name)
			}catch (myerror:Error) {
				trace(myerror)
			}
		}
		public final function addPlus(obj:Object):void {
			for (var name:String in obj) {
				if (obj[name] is Object) {
					var xo:XMLOperate = new XMLOperate()
					add(name, xo)
				}else {
					add(name,obj[name])
				}
			}
		}
		public final function findKey(key:String, findValue:String,findAll:Boolean=false):* {
			var arr:Array=[]
			for (var i:int = 0; i < length; i++) {
				if (this[i][key] == findValue) {
					if (!findAll) {
						return this[i]
					}else {
						arr.push(this[i])
					}
					
				}
			}
			return arr
			//return xmloperate's array or single xmloperate
		}
		private function formatName(str:String = null):String {
			if(str==null)return null
			var index:int = str.lastIndexOf('::')
			if (index != -1) {
				return str.substr(str.lastIndexOf('::')+2)
			}
			return str
		}
		////////////////////list
		private var _list:Array = new Array()
		public final function get list():Array {
			return _list
		}
		////////////////////length
		private var _length:uint = 0
		public final function get length():uint {
			return _length
		}
		////////////////////depth 
		private var _depth:uint = 0
		public final function get depth():uint {
			return _depth
		}
		private final function _depthLoop(data:XMLList,level:uint):uint {
			if (data.children() == emptyXMLList) {
				return level
			}else {
				return _depthLoop(data.children(),level+1)
			}
		}
	}
}